package net.mgsx.product.t2m.modisco.utility;
import java.util.ArrayList;
import java.util.Collection;

import net.mgsx.product.t2m.modisco.Activator;
import net.mgsx.product.t2m.modisco.tools.ModiscoUtils;

import org.eclipse.gmt.modisco.java.ASTNode;
import org.eclipse.gmt.modisco.java.AbstractMethodDeclaration;
import org.eclipse.gmt.modisco.java.AbstractMethodInvocation;
import org.eclipse.gmt.modisco.java.FieldDeclaration;
import org.eclipse.gmt.modisco.java.Initializer;
import org.eclipse.gmt.modisco.infra.common.core.logging.MoDiscoLogger;
import org.eclipse.gmt.modisco.infra.query.core.exception.ModelQueryExecutionException;
import org.eclipse.gmt.modisco.infra.query.core.java.IJavaModelQuery;
import org.eclipse.gmt.modisco.infra.query.core.java.ParameterValueList;

public class CallHierarchy implements IJavaModelQuery<AbstractMethodDeclaration, Collection<ASTNode>> {
	
	public Collection<ASTNode> evaluate(final AbstractMethodDeclaration context, final ParameterValueList parameterValues)
			throws ModelQueryExecutionException {
		
		Collection<ASTNode> result = new ArrayList<ASTNode>();
		
		evaluateRecursive(context, result);

		return result;
	}
	
	private void evaluateRecursive(AbstractMethodDeclaration context, Collection<ASTNode> result)
	{
		result.add(context);
		// 1) see method invocation
		for(AbstractMethodInvocation invocation : context.getUsages())
		{
			AbstractMethodDeclaration caller = ModiscoUtils.getOwner(invocation, AbstractMethodDeclaration.class);
			if(caller == null){
				FieldDeclaration fd = ModiscoUtils.getOwner(invocation, FieldDeclaration.class);
				if(fd == null){
					Initializer ini = ModiscoUtils.getOwner(invocation, Initializer.class);
					if(ini != null){
						// TODO recursive ...
						result.add(ini);
					}else{
						MoDiscoLogger.logWarning(ModiscoUtils.formatMessage("invocation is not in a method declaration", invocation), Activator.getDefault());
					}
				}else{
					// TODO recursive ...
					result.add(fd);
				}
			}else if(!result.contains(caller)){
				evaluateRecursive(caller, result);
			}			
		}
		// 2 see overrides
	}
}
